{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# pip3 install logger https://github.com/UBTEDU/Yan_ADK/archive/latest.tar.gz\n",
    "import time\n",
    "import json\n",
    "\n",
    "import openadk\n",
    "from openadk.rest import ApiException\n",
    "from openadk.models.motions_parameter import MotionsParameter\n",
    "from openadk.models.motions_operation import MotionsOperation\n",
    "from openadk.api.motions_api import MotionsApi\n",
    "from loguru import logger\n",
    "\n",
    "\n",
    "class Robot:\n",
    "    def __init__(self, node=None):\n",
    "        self.node = node\n",
    "        self.configuration = None  # 标识是否连接\n",
    "        self.is_connected = False\n",
    "\n",
    "    def connect(self, robot_ip=\"raspberrypi.local\"):\n",
    "        # 如果未完成，则对robot的调用都弹出提醒\n",
    "        self.configuration = openadk.Configuration()  # openadk global\n",
    "        self.configuration.host = f'http://{robot_ip}:9090/v1'  # /ui\n",
    "        if self.ping_robot() == \"online\":\n",
    "            if self.node:\n",
    "                self.node.pub_notification(\"Device(Yanshee) Connected!\", type=\"SUCCESS\")  # 由一个积木建立连接到时触发\n",
    "            self.is_connected = True\n",
    "            return True\n",
    "\n",
    "    # 装饰器 require connect\n",
    "    def ping_robot(self):\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        self.devices_api_instance = openadk.DevicesApi(\n",
    "            openadk.ApiClient(self.configuration))\n",
    "        try:\n",
    "            # Get system's battery information\n",
    "            api_response = self.devices_api_instance.get_devices_battery()\n",
    "            logger.debug(api_response)\n",
    "            return \"online\"\n",
    "        except ApiException as e:  # global\n",
    "            error_message = f\"Exception when calling DevicesApi->get_devices_battery: {str(e)}\"\n",
    "            logger.error(error_message)\n",
    "            if node:\n",
    "                node.pub_notification(error_message, type=\"ERROR\")\n",
    "\n",
    "    def play(\n",
    "        self,\n",
    "        name=\"wave\",  # GetUp, Hug, Bow , HappyBirthday, Forward Backward OneStepForward TurnLeft TurnRight\n",
    "        operation='start',\n",
    "        direction='both',\n",
    "        speed=\"fast\"):  # ['start', 'pause', 'resume', 'stop']\n",
    "\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        motion_api_instance = MotionsApi(openadk.ApiClient(self.configuration))\n",
    "        timestamp = int(time.time())\n",
    "        kw = {\"name\": name, \"speed\": speed, \"repeat\": 1}\n",
    "        if direction:\n",
    "            kw[\"direction\"] = direction\n",
    "        motion = MotionsParameter(**kw)\n",
    "        body = MotionsOperation(motion=motion,\n",
    "                                operation=operation,\n",
    "                                timestamp=timestamp)\n",
    "        try:\n",
    "            ret = motion_api_instance.put_motions(body)\n",
    "        except ApiException as e:\n",
    "            error_message = f\"Exception when calling DevicesApi->get_devices_battery: {str(e)}\"\n",
    "            logger.error(error_message)\n",
    "            if node:\n",
    "                node.pub_notification(error_message, type=\"ERROR\")\n",
    "        # assert ret.code == 0\n",
    "        return ret\n",
    "\n",
    "    def bow(self):\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        self.play(name=\"bow\", direction=\"\", speed=\"slow\", operation=\"start\")\n",
    "\n",
    "    def say(self, content=\"你好\"):\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        timestamp = int(time.time())\n",
    "        api_instance = openadk.VoiceApi(openadk.ApiClient(self.configuration))\n",
    "        body = openadk.VoiceTTSStr(content)  # VoiceTTSStr |\n",
    "        api_response = api_instance.put_voice_tts(body)\n",
    "        \n",
    "    def start_auto_transform(self):\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        api_instance = openadk.VoiceApi(openadk.ApiClient(self.configuration))\n",
    "        body = openadk.VoiceIatRequest()  # VoiceIatRequest |  (optional)\n",
    "\n",
    "        try:\n",
    "            # Start auto transform\n",
    "            api_response = api_instance.put_voice_iat(body=body)\n",
    "            logger.debug(api_response)\n",
    "        except ApiException as e:\n",
    "            error_message = f\"Exception when calling VoiceApi->put_voice_iat: {str(e)}\"\n",
    "            logger.error(error_message)\n",
    "            if node:\n",
    "                node.pub_notification(error_message, type=\"ERROR\")\n",
    "    \n",
    "    def get_transform_result(self):\n",
    "        if not self.configuration:\n",
    "            return\n",
    "        api_instance = openadk.VoiceApi(openadk.ApiClient(self.configuration))\n",
    "        try:\n",
    "            # Get auto transform(iat) result\n",
    "            api_response = api_instance.get_voice_iat()\n",
    "            logger.debug(api_response)\n",
    "        except ApiException as e:\n",
    "            error_message = f\"Exception when calling VoiceApi->get_voice_iat: {str(e)}\"\n",
    "            logger.error(error_message)\n",
    "            if node:\n",
    "                node.pub_notification(error_message, type=\"ERROR\")\n",
    "        # 接口返回的是以转义字符结尾的字符串，去除转义字符并转为 python dict\n",
    "        normalization_res = api_response.data.replace(\"\\x00\", \"\")\n",
    "        n = json.loads(normalization_res)\n",
    "        # 将结果拼接为语音指令\n",
    "        cmd = \"\"\n",
    "        for i in n['text']['ws']:\n",
    "            cmd += i['cw'][0]['w']\n",
    "        return cmd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "robot = Robot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2020-06-04 16:13:49.938 | DEBUG    | __main__:ping_robot:38 - {'code': 0,\n",
      " 'data': {'charging': 0, 'percent': 91, 'voltage': 4021},\n",
      " 'msg': 'success'}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "robot.connect(\"192.168.31.109\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "robot.bow()\n",
    "robot.say(\"欢迎来到 codelab\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'code': 0, 'data': {'total_time': 3350}, 'msg': 'success'}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "robot.play(name=\"OneStepForward\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'code': 0, 'data': {'total_time': 41430}, 'msg': 'success'}"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "robot.play(name=\"Forward\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "robot.play(name=\"Stop\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2020-06-04 16:11:43.717 | DEBUG    | __main__:start_auto_transform:96 - {'code': 0, 'data': '{}', 'msg': 'Success'}\n"
     ]
    }
   ],
   "source": [
    "robot.start_auto_transform()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2020-06-04 16:13:55.455 | DEBUG    | __main__:get_transform_result:110 - {'code': 0,\n",
      " 'data': '{\"text\":{\"bg\":0,\"ed\":0,\"ls\":false,\"sn\":1,\"ws\":[{\"bg\":0,\"cw\":[{\"sc\":0,\"w\":\"你好\"}]}]}}\\x00',\n",
      " 'msg': 'Success',\n",
      " 'status': 'idle',\n",
      " 'timestamp': None}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'你好'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "robot.get_transform_result() # after start auto transform"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
